﻿/**
  ******************************************************************************
  * @file    Libraries/Device/JS32T031/JS32T031_LL_Driver/src/js32t031_ll_gpio.c
  * @author  JUSHENG Application Team
  * @version V1.0.0
  * @date    02-19-2022
  * @brief   This file contains all the GPIO LL firmware functions.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2022 JUSHENG</center></h2>
  *
  *
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "include.h"

/** @addtogroup JS32T031_StdPeriph_Driver JS32T031 Driver
  * @{
  */
  
/** @defgroup gpio_interface_gr GPIO Driver
  * @ingroup  JS32T031_StdPeriph_Driver
  * @{
  */

/** @addtogroup GPIO_LL_Driver GPIO LL Driver
  * @ingroup  gpio_interface_gr
  * @{
  */
  
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup GPIO_LL_Inti_Cfg GPIO LL Initialization And Configuration
  * @ingroup  GPIO_LL_Driver
  * @brief    GPIO LL Initialization And Configuration
  * @{
  */

/** 
  * @brief  Initializes the GPIOx peripheral.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_initstruct: pointer to a TYPE_LL_GPIO_INIT structure that contains
    *        the configuration information.
  * @retval None.
  */
void ll_gpio_init(GPIO_TypeDef* p_gpio, TYPE_LL_GPIO_INIT* gpio_initstruct)
{
    u16 pos = 0;
    
    for(pos = 0; pos < 16; pos++)
    {
        if((gpio_initstruct->gpio_pin>>pos) & 0x1)
        {
            if((gpio_initstruct->gpio_mode == LL_GPIO_MODE_OUT) || (gpio_initstruct->gpio_mode == LL_GPIO_MODE_AF))
            {
                if(((p_gpio == GPIOA)||((p_gpio == GPIOB)&&(gpio_initstruct->gpio_pin >= LL_GPIO_PIN_8)))&&(gpio_initstruct->gpio_speed_level > LL_GPIO_SPEED_LEVEL_3))
                {
                    if(pos < 8)
                    {
                        p_gpio->OSPEEDL &= ~(0xF << (pos * 4));
                        p_gpio->OSPEEDL |= (0x3 << (pos * 4));
                    }
                    else
                    {
                        p_gpio->OSPEEDH &= ~(0xF << ((pos - 8) * 4));
                        p_gpio->OSPEEDH |= (0x3 << ((pos - 8) * 4));
                    }
                }
                else
                {
                    if(pos < 8)
                    {
                        p_gpio->OSPEEDL &= ~(0xF << (pos * 4));
                        p_gpio->OSPEEDL |= ((gpio_initstruct->gpio_speed_level & 0xF) << (pos * 4));
                    }
                    else
                    {
                        p_gpio->OSPEEDH &= ~(0xF << ((pos - 8) * 4));
                        p_gpio->OSPEEDH |= ((gpio_initstruct->gpio_speed_level & 0x0F) << ((pos - 8) * 4));
                    }
                }
            }
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))) | ((gpio_initstruct->gpio_mode & 0x03) << (pos * 2)));
            p_gpio->TG_EDGE =((p_gpio->TG_EDGE & (~(0x3 << (pos * 2)))) | ((gpio_initstruct->gpio_edge & 0x03) << (pos * 2)));
        }
    }

    if((gpio_initstruct->gpio_mode == LL_GPIO_MODE_OUT) || (gpio_initstruct->gpio_mode == LL_GPIO_MODE_AF))
    {
        if(gpio_initstruct->gpio_type)
        {
            p_gpio->OTYPE |= gpio_initstruct->gpio_pin;
        }
        else
        {
             p_gpio->OTYPE &= ~(gpio_initstruct->gpio_pin);
        }
    }
    else
    {
         p_gpio->OTYPE &= ~(gpio_initstruct->gpio_pin);
    }
    
    if(gpio_initstruct->gpio_pupd == LL_GPIO_PUPD_UP)
    {
        p_gpio->PUPD &= ~(gpio_initstruct->gpio_pin<<16);
        p_gpio->PUPD |= gpio_initstruct->gpio_pin;
    }
    else if(gpio_initstruct->gpio_pupd == LL_GPIO_PUPD_DOWN)
    {
        p_gpio->PUPD &= ~(gpio_initstruct->gpio_pin);
        p_gpio->PUPD |= (gpio_initstruct->gpio_pin<<16);
    }
    else
    {
        p_gpio->PUPD &= ~(gpio_initstruct->gpio_pin<<16);
        p_gpio->PUPD &= ~(gpio_initstruct->gpio_pin);
    }
}

/**
  * @brief  Configure the mode for the specified port pin.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
    *        This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  gpio_mode: Specifies the configuration mode
    *        This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @retval None.
  */
void ll_gpio_set_mode(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_MODE gpio_mode)
{
    u16 pos = 0;
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))) | (gpio_mode << (pos * 2)));
        }
    }
}

/**
  * @brief  Configure the output type for the specified port pin.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
    *        This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  gpio_type: Specifies the output type
    *        This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @retval None.
  */
void ll_gpio_set_type(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_TYPE gpio_type)
{
    if(gpio_type){
        p_gpio->OTYPE |= gpio_pin;
    }
    else{
        p_gpio->OTYPE &= ~(gpio_pin);
    } 
}

/**
  * @brief  Configure the pull-up/pull-down state for the specified port pin.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  gpio_pupd: Specifies the pull-up/pull-down state
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_PUPD enum values.
  * @retval None.
*/
void ll_gpio_set_pupd(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_PUPD gpio_pupd)
{
    if(gpio_pupd == LL_GPIO_PUPD_UP){
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD |= gpio_pin;
    }
    else if(gpio_pupd == LL_GPIO_PUPD_DOWN){
        p_gpio->PUPD &= ~(gpio_pin);
        p_gpio->PUPD |= (gpio_pin<<16);
    }
    else{
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD &= ~(gpio_pin);
    }
}

/**
  * @brief  Configure the mode&out type&pupd for the specified port pin.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  gpio_mode: Specifies the configuration mode
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @param  gpio_type: Specifies the output type
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @param  gpio_pupd: Specifies the pull-up/pull-down state
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_PUPD enum values.
  * @retval None.
*/
void ll_gpio_set_pin(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_MODE gpio_mode, TYPE_ENUM_LL_GPIO_TYPE gpio_type, TYPE_ENUM_LL_GPIO_PUPD gpio_pupd)
{
    u16 pos = 0;
    
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))) | (gpio_mode << (pos * 2)));
        }
    }
    
    if((gpio_mode == LL_GPIO_MODE_OUT) || (gpio_mode == LL_GPIO_MODE_AF)){
        if(gpio_type){
            p_gpio->OTYPE |= gpio_pin;
        }
        else{
             p_gpio->OTYPE &= ~(gpio_pin);
        }
    }
    if(gpio_pupd == LL_GPIO_PUPD_UP){
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD |= gpio_pin;
    }
    else if(gpio_pupd == LL_GPIO_PUPD_DOWN){
        p_gpio->PUPD &= ~(gpio_pin);
        p_gpio->PUPD |= (gpio_pin<<16);
    }
    else{
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD &= ~(gpio_pin);
    }
}

/**
  * @brief  Configure the specified port pin as input mode.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  gpio_pupd: Specifies the pull-up/pull-down state
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_PUPD enum values.
  * @retval None.
*/
void ll_gpio_set_in_mode(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_PUPD gpio_pupd)
{
    u16 pos = 0;
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){ 
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }            
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))));
        }
    }
    
    if(gpio_pupd == LL_GPIO_PUPD_UP){
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD |= gpio_pin;
    }
    else if(gpio_pupd == LL_GPIO_PUPD_DOWN){
        p_gpio->PUPD &= ~(gpio_pin);
        p_gpio->PUPD |= (gpio_pin<<16);
    }
    else{
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD &= ~(gpio_pin);
    }
}

/**
  * @brief  Configure the specified port pin as output mode.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  gpio_type: Specifies the output type
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @param  gpio_pupd: Specifies the pull-up/pull-down state
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_PUPD enum values.
  * @retval None.
*/
void ll_gpio_set_out_mode(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_TYPE gpio_type,TYPE_ENUM_LL_GPIO_PUPD gpio_pupd)
{
    u16 pos = 0;
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){  
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }            
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))) | (0x01 << (pos * 2)));
        }
    }
    
    if(gpio_type){
        p_gpio->OTYPE |= gpio_pin;
    }
    else{
         p_gpio->OTYPE &= ~(gpio_pin);
    }
    
    if(gpio_pupd == LL_GPIO_PUPD_UP){
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD |= gpio_pin;
    }
    else if(gpio_pupd == LL_GPIO_PUPD_DOWN){
        p_gpio->PUPD &= ~(gpio_pin);
        p_gpio->PUPD |= (gpio_pin<<16);
    }
    else{
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD &= ~(gpio_pin);
    }
}

/**
  * @brief  Configure the specified port pin as analog mode.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @retval None.
*/
void ll_gpio_set_an_mode(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    u16 pos = 0;
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){   
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }            
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))) | (0x03 << (pos * 2)));
        }
    }
}

/**
  * @brief  Configure the specified port pin for work.
  * @param  p_gpio: can be GPIOx where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be Configured.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  my_mode: Specifies the type
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @retval None.
*/
void ll_gpio_config(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_ALL_MODE my_mode)
{
    switch(my_mode){
        case LL_GPIO_MD_IN_NOPULL:
            //ll_gpio_set_in_mode(p_gpio, gpio_pin, LL_GPIO_PUPD_NOPULL);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_IN, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_NOPULL);
            break;
        case LL_GPIO_MD_IN_UP:
            //ll_gpio_set_in_mode(p_gpio, gpio_pin, LL_GPIO_PUPD_UP);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_IN, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_UP);
            break;
        case LL_GPIO_MD_IN_DOWN:
            //ll_gpio_set_in_mode(p_gpio, gpio_pin, LL_GPIO_PUPD_DOWN);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_IN, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_DOWN);
            break;
        case LL_GPIO_MD_OUT_PP:
            //ll_gpio_set_out_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_NOPULL);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_OUT, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_NOPULL);
            break;
        case LL_GPIO_MD_OUT_OD_NOPULL:
            //ll_gpio_set_out_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_NOPULL);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_OUT, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_NOPULL);
            break;
        case LL_GPIO_MD_OUT_OD_UP:
            //ll_gpio_set_out_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_UP);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_OUT, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_UP);
            break;
                
        case LL_GPIO_MD_AF_NOPULL:
            //ll_gpio_set_out_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_NOPULL);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AF, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_NOPULL);
            break;
        case LL_GPIO_MD_AF_UP:
            //ll_gpio_set_out_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_UP);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AF, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_UP);
            break;                
        case LL_GPIO_MD_AF_DOWN:
            //ll_gpio_set_out_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_DOWN);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AF, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_DOWN);
            break;                    
        case LL_GPIO_MD_AF_PP:
            //ll_gpio_set_af_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_NOPULL);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AF, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_NOPULL);
            break;
        case LL_GPIO_MD_AF_OD_NOPULL:
            //ll_gpio_set_af_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_NOPULL);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AF, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_NOPULL);
            break;
        case LL_GPIO_MD_AF_OD_UP:
            //ll_gpio_set_af_mode(p_gpio, gpio_pin, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_UP);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AF, LL_GPIO_TYPE_OUT_OD, LL_GPIO_PUPD_UP);
            break;
        case LL_GPIO_MD_AN:
            //ll_gpio_set_an_mode(p_gpio, gpio_pin);
            ll_gpio_set_pin(p_gpio, gpio_pin, LL_GPIO_MODE_AN, LL_GPIO_TYPE_OUT_PP, LL_GPIO_PUPD_NOPULL);
            break;
        default:
            break;
    }    
}

/**
  * @brief  Config gpio speed level.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  * @param  gpio speed level: gpio speed level(LEVEL0-7)
  *   This parameter can be one of the TYPE_ENUM_LL_GPIO_MODE enum values.
  * @retval None.
  */
void ll_gpio_set_speed(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_SPEED_LEVEL gpio_speed_level)
{
    u16 pos = 0;

    for(pos = 0; pos < 16; pos++)
    {
        if(!((gpio_pin >> pos) & 0x1))
        continue;
        
        if(((p_gpio == GPIOA)||((p_gpio == GPIOB)&&(gpio_pin >= LL_GPIO_PIN_8)))&&(gpio_speed_level > LL_GPIO_SPEED_LEVEL_3))
        {
            if(pos < 8)
            {
                p_gpio->OSPEEDL &= ~(0xF << (pos * 4));
                p_gpio->OSPEEDL |= (0x3 << (pos * 4));
            }
            else
            {
                p_gpio->OSPEEDH &= ~(0xF << ((pos - 8) * 4));
                p_gpio->OSPEEDH |= (0x3 << ((pos - 8) * 4));
            }
        }
        else
        {
            if(pos < 8)
            {
                p_gpio->OSPEEDL &= ~(0xF << (pos * 4));
                p_gpio->OSPEEDL |= ((gpio_speed_level & 0xF) << (pos * 4));
            }
            else
            {
                p_gpio->OSPEEDH &= ~(0xF << ((pos - 8) * 4));
                p_gpio->OSPEEDH |= ((gpio_speed_level & 0x0F) << ((pos - 8) * 4));
            }
        }
        
    }
}

/**
  * @brief  Config gpio pin alternate function mode.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  * @param  gpio type(push-pull/open-drain)
  * @param  gpio_pupd: gpio pull type(pull-up/pull-down)
  * @retval None.
  */
void ll_gpio_set_af_mode(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_TYPE gpio_type,TYPE_ENUM_LL_GPIO_PUPD gpio_pupd)
{
    u16 pos = 0;
        
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){
            if(USING_TS32F020D_CHIP==true && pos>=10)
            {
                if(p_gpio == GPIOA && pos==14)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (11 * 2)));
                }
                else if(p_gpio == GPIOA && pos==15)
                {
                        GPIOB->MODE=GPIOB->MODE & (~(0x3 << (10 * 2)));
                }
                else if(p_gpio == GPIOB && pos==10)
                {
                        GPIOA->MODE=GPIOA->MODE & (~((u32)0x3 << (15 * 2)));
                }
                else if(p_gpio == GPIOB && pos==11)
                {
                        GPIOA->MODE=GPIOA->MODE & (~(0x3 << (14 * 2)));
                }
            }
            p_gpio->MODE =((p_gpio->MODE & (~(0x3 << (pos * 2)))) | (0x02 << (pos * 2)));
        }
    }
    
    if(gpio_type){
        p_gpio->OTYPE |= gpio_pin;
    }
    else{
         p_gpio->OTYPE &= ~(gpio_pin);
    }
    
    if(gpio_pupd == LL_GPIO_PUPD_UP){
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD |= gpio_pin;
    }
    else if(gpio_pupd == LL_GPIO_PUPD_DOWN){
        p_gpio->PUPD &= ~(gpio_pin);
        p_gpio->PUPD |= (gpio_pin<<16);
    }
    else{
        p_gpio->PUPD &= ~(gpio_pin<<16);
        p_gpio->PUPD &= ~(gpio_pin);
    }
}

/**
  * @brief  Config gpio pin alternate function mode.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  * @param  gpio_af:(LL_GPIO_AF_0/LL_GPIO_AF_1)
  * @retval None.
  */
void ll_gpio_af_sel(GPIO_TypeDef* p_gpio, u16 gpio_pin, TYPE_ENUM_LL_GPIO_AF gpio_af)
{
    u16 gpio_pin_src = 0x00;
    u32 temp = 0x00;
    u32 temp_2 = 0x00;
   
    for(gpio_pin_src = 0; gpio_pin_src < 16; gpio_pin_src++){
        if((gpio_pin>>gpio_pin_src)&0x01)
        {
            temp = ((u32)(gpio_af) << ((u32)((u32)gpio_pin_src & (u32)0x07) * 4));
            p_gpio->AFR[gpio_pin_src >> 0x03] &= ~((u32)0xF << ((u32)((u32)gpio_pin_src & (u32)0x07) * 4));
            temp_2 = p_gpio->AFR[gpio_pin_src >> 0x03] | temp;
            p_gpio->AFR[gpio_pin_src >> 0x03] = temp_2;
        }
    }
}

/**
  * @brief  Sets the selected data port bits.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @retval None.
  */
void ll_gpio_set_bits(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{ 
    p_gpio->BSR = (u16)gpio_pin;
}

/**
  * @brief  Clears the selected data port bits.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @retval None.
  */
void ll_gpio_reset_bits(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->BSR = (u32)gpio_pin <<16;
}

/**
  * @brief  Config gpio port toggle.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *   This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15). 
  * @retval None.
  */
void ll_gpio_toggle(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->TGL = gpio_pin;
}

/**
  * @brief  Write the specified GPIO output data port.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_set_value: gpio set value.
  * @retval None.
  */
void ll_gpio_write_data(GPIO_TypeDef* p_gpio, u32 gpio_set_value)
{
    p_gpio->ODAT = gpio_set_value;
}
/**
  * @brief  Reads the specified GPIO output data port.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @retval GPIO output data port value.
  */
u16 ll_gpio_read_output_data(GPIO_TypeDef* p_gpio)
{
    return ((u16)p_gpio->ODAT);
}

/**
  * @brief  Read the specified output data port bit.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: Specifies the port bit to read.
  * @note   This parameter can be LL_GPIO_PIN_x where x can be:(0..15) for GPIOA, 
  *   (0..9) for GPIOB.
  * @retval The output port pin value.
  */
u8 ll_gpio_read_output_data_bit(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    uint8_t bitstatus = 0x00;

    if ((p_gpio->ODAT & gpio_pin) != (u32)LL_GPIO_RESET)
    {
        bitstatus = (uint8_t)LL_GPIO_SET;
    }
    else
    {
        bitstatus = (uint8_t)LL_GPIO_RESET;
    }
    return bitstatus;
}

/**
  * @brief  Reads the specified input port pin.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @retval The input port pin value.
  */
u16 ll_gpio_read_input_data(GPIO_TypeDef* p_gpio)
{
    return ((u16)p_gpio->IDAT);
}

/**
  * @brief  Reads the specified input port pin.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to read.
  * @note   This parameter can be LL_GPIO_PIN_x where x can be:(0..15) for GPIOA, 
  *   (0..9) for GPIOB.
  * @retval The input port pin value.
  */
u8 ll_gpio_read_input_data_bit(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    u8 bitstatus = 0x00;

    if ((p_gpio->IDAT & gpio_pin) != (u32)LL_GPIO_RESET)
    {
        bitstatus = (u8)LL_GPIO_SET;
    }
    else
    {
        bitstatus = (u8)LL_GPIO_RESET;
    }
    return bitstatus;
}

/**
  * @brief  Writes data to the specified GPIO data port.
  * @param  p_gpio: where x can be (A or B) to select the GPIO peripheral.
  * @param  gpio_pin_src: specifies the pin for the Alternate function.
  *          This parameter can be GPIO_PinSourcex where x can be (0..15).
  * @param  gpio_af: selects the pin to used as Alternate function.
  *          This parameter can be one of the following value:
  *            @arg LL_GPIO_AF_0   
  *            @arg LL_GPIO_AF_1   

  * @note   The pin should already been configured in Alternate Function mode(AF)
  *         using GPIO_InitStruct->GPIO_MODE = GPIO_MODE_AF.
  * @note   Refer to the Alternate function mapping table in the device datasheet 
  *         for the detailed mapping of the system and peripherals'alternate 
  *         function I/O pins.
  * @retval None.
  */
void ll_gpio_pin_af_config(GPIO_TypeDef* p_gpio, u16 gpio_pin_src, TYPE_ENUM_LL_GPIO_AF gpio_af)
{
    u32 temp = 0x00;
    u32 temp_2 = 0x00;

    temp = ((u32)(gpio_af) << ((u32)((u32)gpio_pin_src & (u32)0x07) * 4));
    p_gpio->AFR[gpio_pin_src >> 0x03] &= ~((u32)0xF << ((u32)((u32)gpio_pin_src & (u32)0x07) * 4));
    temp_2 = p_gpio->AFR[gpio_pin_src >> 0x03] | temp;
    p_gpio->AFR[gpio_pin_src >> 0x03] = temp_2;
}

/**
  * @brief  Config gpio irq.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  edge£RRISING or FALLING
  * @param  newstate: DISABLE or ENABLE.
  * @retval None.
  */
void ll_gpio_irq_config(GPIO_TypeDef* p_gpio, u16 gpio_pin, TPYE_ENUM_LL_GPIO_TG_EDGE edge)
{
    u16 pos = 0;
        
    for(pos = 0; pos < 16; pos++){
        if((gpio_pin>>pos) & 0x1){
            p_gpio->TG_EDGE =((p_gpio->TG_EDGE & (~(0x3 << (pos * 2)))) | (edge << (pos * 2)));
        }
    }
}

/**
  * @brief  gpio irq enable.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @param  newstate: DISABLE or ENABLE.
  * @retval None.
  */
void ll_gpio_irq_enable(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->IMK |= gpio_pin;
}

/**
  * @brief  gpio irq enable.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15).
  * @retval None.
  */
void ll_gpio_irq_disable(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->IMK &= ~gpio_pin;
}

/**
  * @brief  Clear gpio port pending.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15). 
  * @retval None.
  */
void ll_gpio_port_pend_clear(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->TGPEND = gpio_pin;
}

/**
  * @brief  Get gpio port pending.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15). 
  * @retval The selected port pending value.
  */
u32 ll_gpio_port_pend_get(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    if(p_gpio->TGPEND & gpio_pin)
        return 1;
    else
        return 0;
}

/**
  * @brief  enable gpio ie en.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15). 
  * @retval None.
  */
void ll_gpio_port_ieen_enable(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->IE_EN |= gpio_pin;
}

/**
  * @brief  disable gpio ie en.
  * @param  p_gpio: where x can be (A..B) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of LL_GPIO_PIN_x where x can be (0..15). 
  * @retval None.
  */
void ll_gpio_port_ieen_disable(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->IE_EN &= ~gpio_pin;
}

/**
  * @}
  */

/** @defgroup GPIO_LL_Data_Transfers GPIO LL Data transfers functions
  * @ingroup  GPIO_LL_Driver
  * @brief    GPIO LL Data transfers functions 
  * @{
  */



/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/*************************** (C) COPYRIGHT 2022 JUSHENG ***** END OF FILE *****/
